//创建axios构造函数
function Axios(config) {
  //配置文件
  this.default = config || {}
  //拦截器
  this.interceptors = {
    request: new InterceptorsManage(),
    response: new InterceptorsManage()
  }
}
//request
Axios.prototype.request = function (config) {
  Object.assign(this.default, config)
  let promise = Promise.resolve(this.default);
  //声明一个数组
  let chains = [dispatchRequest, undefined]; // undefined 占位

  // 请求拦截 成功失败拦截 前面插入
  this.interceptors.request.handler.forEach(item => {
    chains.unshift(item.fulfilled, item.failed)
  });

  // 响应拦截 成功失败拦截 后面插入
  this.interceptors.response.handler.forEach(item => {
    chains.push(item.fulfilled, item.failed)
  });

  // 请求config 响应config 通过permisson链式传递
  while (chains.length) {
    promise = promise.then(chains.shift(), chains.shift());
  }
  return promise
}
//get请求
Axios.prototype.get = function (url) {
  return this.request({
    method: "GET",
    url
  })
}
//post请求
Axios.prototype.post = function (url) {
  return this.request({
    method: "POST",
    url
  })
}
// 拦截器管理
function InterceptorsManage() {
  this.handler = []
}
// use方法
InterceptorsManage.prototype.use = function (fulfilled, failed) {
  this.handler.push({
    fulfilled,
    failed
  })
}

// 取消请求方法 通过permise resolve暴露方法出去
function CancelToken(executor) {
  var resolvePromise;
  this.promise = new Promise((resolve, reject) => {
    resolvePromise = resolve
  })
  executor(function () {
    resolvePromise()
  })
}

// 通过createInstance创建 axios
function createInstance(config) {
  // 创建Axios实例
  let context = new Axios(config)
  // axios().then()直接请求
  let instance = Axios.prototype.request.bind(context)
  //  instance复制content里的内容,可调用Axios里面的方法
  for (let keys in context) {
    instance[keys] = context[keys]
  }
  return instance
}
// 配置合并 暂时 http https
function mergeConfig(config) {
  if (config.url.indexOf('http://') < 0 && config.url.indexOf('https://')) {
    config.url = config.baseUrl + config.url
  }
  return config
}

function dispatchRequest(config) {
  config = mergeConfig(config)
  return xhrAdapter(config).then(res => {
    return res
  }).catch(error => {
    throw error
  })
}
//封装xhr方法
function xhrAdapter(config) {
  console.log(config);
  return new Promise((resolve, reject) => {
    // 创建xhr实例
    var xhr = new XMLHttpRequest()
    xhr.open(config.method, config.url)
    xhr.send()
    // 监听xhr状态
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        console.log(xhr);
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve({
            //配置对象
            config: config,
            //响应体
            data: xhr.response,
            //响应头
            headers: xhr.getAllResponseHeaders(), //字符串  parseHeaders
            // xhr 请求对象
            request: xhr,
            //响应状态码
            status: xhr.status,
            //响应状态字符串
            statusText: xhr.statusText
          })
        } else {
          reject('请求失败')
        }
      }
    }
    if (config.cancelToken) {
      // 通过promise resolve触发关闭请求
      config.cancelToken.promise.then(() => {
        xhr.abort()
        console.log('取消请求');
      }).catch(() => {
        console.log("请求失败")
      })
    }
  })
}